package com.example.order;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 开启 Feign 远程调用功能
 */
@EnableFeignClients
/**
 * 开启服务发现功能
 */
@EnableDiscoveryClient
@SpringBootApplication
public class OrderMainApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderMainApplication.class, args);
    }

    /**
     * Nacos 配置变更监听器注册逻辑
     * 利用了 Nacos 提供的低层 API：ConfigService.addListener(...) 来监听配置文件的变化，并在变更时触发操作（比如发送邮件、记录日志等）。
     * 在应用启动时，监听 Nacos 配置中心中的某个配置文件（service-order.yaml），一旦有变更就回调方法，并执行某些自定义逻辑（如日志记录、邮件通知等）。
     * <p></p>
     * 使用了 Spring Cloud Alibaba 中的底层 Nacos 客户端 API：
     * 组件	                作用
     * NacosConfigManager	Spring Cloud 封装的 Nacos 配置管理器
     * ConfigService	    Nacos 原生客户端提供的配置操作 API
     * addListener(...)	    注册监听器，监听指定 DataID + Group 的配置变化
     * <p></p>
     * 1.Spring Boot 启动
     * 2.执行 ApplicationRunner
     * 3.获取 Nacos 配置服务 ConfigService
     * 4.注册监听器（监听 DataID）
     * 5.当配置发生变更
     * 6.receiveConfigInfo 被自动回调
     * 7.获取新配置 → 打印/发邮件/通知
     */
    @Bean
    /**
     * 🔹 ApplicationRunner 是 Spring Boot 提供的一个接口。
     * 它的作用是：在 Spring Boot 项目启动完成后立即执行自定义代码逻辑。
     * 方法参数 NacosConfigManager 是 Spring Cloud Alibaba 自动注入的 Nacos 配置服务管理器。
     * Spring Boot 会自动将容器中已有的 Bean（比如 NacosConfigManager）注入到这个方法参数中。
     * 这是 Spring 容器的依赖注入机制（DI） 在 Bean 方法中的自然应用。
     * <p></p>
     * 这是一个方法签名，意思是：
     * 方法名叫：applicationRunner
     * 方法返回类型是：ApplicationRunner
     * 方法接收一个参数：NacosConfigManager 类型的对象
     */
    ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
        return args -> {
            String dataId = "service-order.yaml";
            String group = "DEFAULT_GROUP";
            /**
             * 从 Spring Cloud Alibaba 提供的 NacosConfigManager 中获取 Nacos 原生配置服务 ConfigService。
             * 这个对象可以用来：
             * 获取配置内容（getConfig(...)）
             * 发布配置（publishConfig(...)）
             * 监听配置变更（addListener(...)）✅ 当前用到的
             */
            ConfigService configService = nacosConfigManager.getConfigService();
            /**
             * 这是向 Nacos 注册一个监听器：
             * DataID：`service-order.yaml`
             * Group：`DEFAULT_GROUP`
             * 当 `service-order.yaml` 文件的内容发生变化时，就会触发后面传入的 `Listener` 接口实例中的方法。
             */
            configService.addListener(dataId, group,
                    new Listener() {
                        /**
                         * getExecutor() 是监听器接口中的一个方法。
                         * 返回一个线程池，用于执行回调任务的线程环境。
                         * 🔧 返回的是固定线程数为 4 的线程池，意味着最多 4 个配置变更通知可以并发处理。
                         * 如果返回 null，则使用默认线程池。
                         */
                        @Override
                        public Executor getExecutor() {
                            return Executors.newFixedThreadPool(4); // 异步监听线程池
                        }

                        /**
                         * receiveConfigInfo(String configInfo) 是回调方法：
                         * 当你在 Nacos 控制台修改 service-order.yaml 并发布时：
                         * Spring Cloud Alibaba 内部监听到变化
                         * 调用你注册的 Listener.receiveConfigInfo(...)
                         * configInfo 参数就是变化之后的整个文件内容
                         */
                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            System.out.println("配置变更后的内容" + configInfo); // 配置变更后的内容
                            // TODO: 调用邮件服务、日志记录、消息推送等
                            System.out.println("模拟通知逻辑"); // 模拟通知逻辑
                        }
                    });
            System.out.println("✅ Nacos 配置监听器已启动，监听：" + dataId);
        };
    }

}
